package com.fulu.game.bi.service.impl.dispatch;


import cn.hutool.core.date.DateUtil;
import com.fulu.game.bi.common.util.csv.CsvExportUtil;
import com.fulu.game.bi.common.util.csv.Mapper;
import com.fulu.game.bi.common.util.csv.Querier;
import com.fulu.game.bi.common.util.math.MathUtils;
import com.fulu.game.bi.entity.bo.channel.ExposurePlayeeOverviewListBO;
import com.fulu.game.bi.entity.dto.ExposurePlayeeDetailListDTO;
import com.fulu.game.bi.entity.dto.ExposurePlayeeOverviewListDTO;
import com.fulu.game.bi.entity.enums.QueryTypeStatusEnum;
import com.fulu.game.bi.entity.vo.dispatch.ExposurePlayeeDetailListVO;
import com.fulu.game.bi.entity.vo.dispatch.ExposurePlayeeOverviewListVO;
import com.fulu.game.bi.entity.vo.dispatch.PlayeeExposureRealtimeVO;
import com.fulu.game.bi.hbase.HBasePlayeeExposureStatDAO;
import com.fulu.game.bi.mysql.playadmin.BuffConfigDao;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class PlayeeExposureStatServiceImpl {
    @Autowired
    private HBasePlayeeExposureStatDAO hBasePlayeeExposureStatDAO;
    @Autowired
    private BuffConfigDao buffConfigDao;

    public static final Map<Integer, String> exposurePlayeeStatMap;

    public static final Map<Integer, String> exposurePlayeeSummaryStatMap;

    static {
        exposurePlayeeStatMap = new HashMap<>();
        exposurePlayeeStatMap.put(QueryTypeStatusEnum.DAY.getType(), "exposure_playee_stat_day");
        exposurePlayeeStatMap.put(QueryTypeStatusEnum.WEEK.getType(), "exposure_playee_stat_week");
        exposurePlayeeStatMap.put(QueryTypeStatusEnum.MONTH.getType(), "exposure_playee_stat_month");

        exposurePlayeeSummaryStatMap = new HashMap<>();
        exposurePlayeeSummaryStatMap.put(QueryTypeStatusEnum.DAY.getType(), "exposure_playee_summary_stat_day");
        exposurePlayeeSummaryStatMap.put(QueryTypeStatusEnum.WEEK.getType(), "exposure_playee_summary_stat_week");
        exposurePlayeeSummaryStatMap.put(QueryTypeStatusEnum.MONTH.getType(), "exposure_playee_summary_stat_month");
    }

    public List<PlayeeExposureRealtimeVO> overviewRealtime() {
        PlayeeExposureRealtimeVO today = hBasePlayeeExposureStatDAO.findByParameter(DateUtil.today());
        today = today == null ? new PlayeeExposureRealtimeVO() : today;
        PlayeeExposureRealtimeVO yesterday = hBasePlayeeExposureStatDAO.findByParameter(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1)));
        yesterday = yesterday == null ? new PlayeeExposureRealtimeVO() : yesterday;
        PlayeeExposureRealtimeVO theDayBeforeYesterday = hBasePlayeeExposureStatDAO.findByParameter(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -2)));
        theDayBeforeYesterday = theDayBeforeYesterday == null ? new PlayeeExposureRealtimeVO() : theDayBeforeYesterday;
        PlayeeExposureRealtimeVO lastWeekYesterdaySameDay = hBasePlayeeExposureStatDAO.findByParameter(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -8)));
        lastWeekYesterdaySameDay = lastWeekYesterdaySameDay == null ? new PlayeeExposureRealtimeVO() : lastWeekYesterdaySameDay;
        List<PlayeeExposureRealtimeVO> list = new ArrayList<>();
        yesterday.setExposureUserNumDay(MathUtils.chainRatio(yesterday.getExposureUserNum(), theDayBeforeYesterday.getExposureUserNum()));
        yesterday.setExposureUserNumWeek(MathUtils.chainRatio(yesterday.getExposureUserNum(), lastWeekYesterdaySameDay.getExposureUserNum()));
        yesterday.setExposureNumDay(MathUtils.chainRatio(yesterday.getExposureNum(), theDayBeforeYesterday.getExposureNum()));
        yesterday.setExposureNumWeek(MathUtils.chainRatio(yesterday.getExposureNum(), lastWeekYesterdaySameDay.getExposureNum()));
        yesterday.setHomePageUserNumDay(MathUtils.chainRatio(yesterday.getHomePageUserNum(), theDayBeforeYesterday.getHomePageUserNum()));
        yesterday.setHomePageUserNumWeek(MathUtils.chainRatio(yesterday.getHomePageUserNum(), lastWeekYesterdaySameDay.getHomePageUserNum()));
        yesterday.setHomePageNumDay(MathUtils.chainRatio(yesterday.getHomePageNum(), theDayBeforeYesterday.getHomePageNum()));
        yesterday.setHomePageNumWeek(MathUtils.chainRatio(yesterday.getHomePageNum(), lastWeekYesterdaySameDay.getHomePageNum()));
        yesterday.setCtrDay(MathUtils.chainRatio(yesterday.getCtr(), theDayBeforeYesterday.getCtr()));
        yesterday.setCtrWeek(MathUtils.chainRatio(yesterday.getCtr(), lastWeekYesterdaySameDay.getCtr()));
        yesterday.setOrderUserNumDay(MathUtils.chainRatio(yesterday.getOrderUserNum(), theDayBeforeYesterday.getOrderUserNum()));
        yesterday.setOrderUserNumWeek(MathUtils.chainRatio(yesterday.getOrderUserNum(), lastWeekYesterdaySameDay.getOrderUserNum()));
        yesterday.setOrderNumDay(MathUtils.chainRatio(yesterday.getOrderNum(), theDayBeforeYesterday.getOrderNum()));
        yesterday.setOrderNumWeek(MathUtils.chainRatio(yesterday.getOrderNum(), lastWeekYesterdaySameDay.getOrderNum()));
        yesterday.setCvrDay(MathUtils.chainRatio(yesterday.getCvr(), theDayBeforeYesterday.getCvr()));
        yesterday.setCvrWeek(MathUtils.chainRatio(yesterday.getCvr(), lastWeekYesterdaySameDay.getCvr()));
        list.add(today);
        list.add(yesterday);
        return list;
    }

    public List<ExposurePlayeeOverviewListVO> overviewList(ExposurePlayeeOverviewListDTO dto) {
        ExposurePlayeeOverviewListBO bo = new ExposurePlayeeOverviewListBO();
        BeanUtils.copyProperties(dto, bo);
        bo.setTableName(exposurePlayeeSummaryStatMap.get(dto.getQueryType()));
        bo.setStrategyIdStr(dto.getStrategyId() != null ? dto.getStrategyId() + "" : null);
        List<ExposurePlayeeOverviewListVO> list = hBasePlayeeExposureStatDAO.list(bo);
        return list.stream().map(map -> {
            map.setQueryType(dto.getQueryType());
            map.setScene(StringUtils.isBlank(dto.getScene()) ? "/" : dto.getScene());
            map.setStrategy(StringUtils.isBlank(dto.getStrategyName()) ? "/" : dto.getStrategyName());
            return map;
        }).collect(Collectors.toList());
    }

    public void overviewListExport(ExposurePlayeeOverviewListDTO dto) {
        String fileName = "陪玩师曝光总览";
        LinkedHashMap<String, Mapper<ExposurePlayeeOverviewListVO>> map = new LinkedHashMap<>();
        QueryTypeStatusEnum anEnum = QueryTypeStatusEnum.getEnum(dto.getQueryType());
        switch (anEnum) {
            case DAY:
                map.put("日期", v -> v.getStartDate());
                break;
            default:
                map.put("日期", v -> v.getStartDate() + "-" + v.getEndDate());
                break;
        }
        map.put("场景", v -> v.getScene());
        map.put("人工策略组", v -> v.getStrategy());
        map.put("曝光人数", v -> v.getExposureUserNum() + "");
        map.put("曝光次数", v -> v.getExposureNum() + "");
        map.put("主页浏览人数", v -> v.getHomePageUserNum() + "");
        map.put("主页浏览次数", v -> v.getHomePageNum() + "");
        map.put("CTR", v -> v.getCtr() + "");
        map.put("下单人数", v -> v.getOrderUserNum() + "");
        map.put("下单次数", v -> v.getOrderNum() + "");
        map.put("CVR", v -> v.getCvr() + "");
        Querier querier = (num) -> {
            PageInfo<ExposurePlayeeOverviewListVO> pageInfo = new PageInfo<>(overviewList(dto));
            pageInfo.setHasNextPage(false);
            return pageInfo;
        };
        CsvExportUtil.export(100, fileName, map, querier);
    }

    public PageInfo<ExposurePlayeeDetailListVO> detailList(ExposurePlayeeDetailListDTO dto) {
        ExposurePlayeeOverviewListBO bo = new ExposurePlayeeOverviewListBO();
        BeanUtils.copyProperties(dto, bo);
        String[] userIds = {};
        if (dto.getStrategyId() != null) {
            String userIdStr = buffConfigDao.findById(dto.getStrategyId());
            if (StringUtils.isBlank(userIdStr)) {
                return new PageInfo<>();
            }
            userIds = userIdStr.split(",");
            bo.setUserIds(Arrays.asList(userIds));
            if (StringUtils.isNotBlank(dto.getUserId())) {
                if (!bo.getUserIds().contains(dto.getUserId())) {
                    return new PageInfo<>();
                } else {
                    bo.setUserIds(Arrays.asList(dto.getUserId()));
                }
            }
        } else {
            bo.setUserIds(dto.getUserId() == null ? null : Arrays.asList(dto.getUserId()));
        }
        bo.setTableName(exposurePlayeeStatMap.get(dto.getQueryType()));
        bo.setNickName(StringUtils.isBlank(bo.getNickName()) ? null : "%" + bo.getNickName() + "%");
        bo.setPageNum((bo.getPageNum() - 1) * bo.getPageSize());
        List<ExposurePlayeeDetailListVO> list = hBasePlayeeExposureStatDAO.detailList(bo);
        Integer count = hBasePlayeeExposureStatDAO.count(bo);
        List<ExposurePlayeeDetailListVO> vos = list.stream().map(map -> {
            map.setQueryType(dto.getQueryType());
            map.setScene(StringUtils.isBlank(dto.getScene()) ? "/" : dto.getScene());
            map.setStrategy(StringUtils.isBlank(dto.getStrategyName()) ? "/" : dto.getStrategyName());
            return map;
        }).collect(Collectors.toList());
        PageInfo<ExposurePlayeeDetailListVO> pageInfo = new PageInfo<>(vos);
        pageInfo.setTotal(count == null ? 0 : count);
        return pageInfo;
    }

    public void detailExport(ExposurePlayeeDetailListDTO dto) {
        String fileName = "陪玩师曝光数据";
        LinkedHashMap<String, Mapper<ExposurePlayeeDetailListVO>> map = new LinkedHashMap<>();
        QueryTypeStatusEnum anEnum = QueryTypeStatusEnum.getEnum(dto.getQueryType());
        switch (anEnum) {
            case DAY:
                map.put("日期", v -> v.getStartDate());
                break;
            default:
                map.put("日期", v -> v.getStartDate() + "-" + v.getEndDate());
                break;
        }
        map.put("用户ID", v -> v.getUserId().toString());
        map.put("用户昵称", v -> v.getNickName());
        map.put("场景", v -> v.getScene());
        map.put("人工策略组", v -> v.getStrategy());
        map.put("曝光人数", v -> v.getExposureUserNum() + "");
        map.put("曝光次数", v -> v.getExposureNum() + "");
        map.put("主页浏览人数", v -> v.getHomePageUserNum() + "");
        map.put("主页浏览次数", v -> v.getHomePageNum() + "");
        map.put("CTR", v -> v.getCtr() + "");
        map.put("下单人数", v -> v.getOrderUserNum() + "");
        map.put("下单次数", v -> v.getOrderNum() + "");
        map.put("CVR", v -> v.getCvr() + "");
        Querier querier = (num) -> detailList(dto);
        CsvExportUtil.export(100, fileName, map, querier);
    }
}
